package cn.cosmosx.base.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.UnknownHostException;

@Slf4j
public abstract class IPUtil {

    final static String UNKNOWN = "unknown";
    final static String LOCALHOST_IPv4 = "127.0.0.1";
    final static String LOCALHOST_IPv6 = "0:0:0:0:0:0:0:1";
    // 请求头
    static final String[] HEADERS_TO_TRY = {"Proxy-Client-IP", "WL-Proxy-Client-IP", "HTTP_X_FORWARDED_FOR", "HTTP_X_FORWARDED", "HTTP_X_CLUSTER_CLIENT_IP", "HTTP_CLIENT_IP", "HTTP_FORWARDED_FOR", "HTTP_FORWARDED", "HTTP_VIA", "REMOTE_ADDR", "X-Real-IP"};


    /**
     * 如果网站设置了nginx反向代理
     * 需要在nginx配置文件加上如下配置才能获取用户真实ip
     * proxy_set_header Host $host;
     * proxy_set_header X-Real-IP $remote_addr;
     * proxy_set_header REMOTE-HOST $remote_addr;
     * proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
     */
    public static String getRealIP(HttpServletRequest request) {
        if (request == null) {
            return LOCALHOST_IPv4;
        }
        String ip = request.getHeader("X-Forwarded-For");
        if (StringUtils.isNotEmpty(ip) && !UNKNOWN.equalsIgnoreCase(ip)) {
            // 多次反向代理后会有多个ip值，第一个ip才是真实ip
            if (ip.contains(",")) {
                ip = ip.split(",")[0];
            }
            return ip;
        }
        for (String key : HEADERS_TO_TRY) {
            ip = request.getHeader(key);
            if (StringUtils.isNotEmpty(ip)) {
                return ip;
            }
        }
        if (LOCALHOST_IPv4.equals(request.getRemoteAddr())
                || LOCALHOST_IPv6.equals(request.getRemoteAddr())) {
            try {
                // 根据网卡获取真实IP
                return InetAddress.getLocalHost().getHostAddress();
            } catch (UnknownHostException e) {
                log.error("UnknownHostException异常", e);
            }
        }
        return request.getRemoteAddr();
    }

    public static String getLocalIp() {
        try {
            return InetAddress.getLocalHost().getHostAddress();
        } catch (Exception ignored) {
        }
        return null;
    }
}
